const {
    mouse,
    straightTo,
} = require('@nut-tree-fork/nut-js');
const { Button } = require('@nut-tree-fork/nut-js');
const path = require('path');
const fs = require('fs');

// ===== 配置文件管理 =====
const CONFIG_FILE = path.join(__dirname, 'config.json');

// 读取配置文件
function loadConfig() {
    try {
        if (fs.existsSync(CONFIG_FILE)) {
            const configData = fs.readFileSync(CONFIG_FILE, 'utf8');
            const config = JSON.parse(configData);
            console.log('📁 已加载配置文件');
            return { ...config };
        } else {
            console.log('📁 配置文件不存在！');
        }
    } catch (error) {
        console.log('⚠️ 配置文件读取失败！', error.message);
    }
}

// 保存配置文件
function saveConfig(config) {
    try {
        fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), 'utf8');
        console.log('💾 配置文件已保存');
        return true;
    } catch (error) {
        console.error('❌ 配置文件保存失败:', error.message);
        return false;
    }
}

// 确保配置项默认值
function ensureConfigDefaults(config) {
    const safe = config && typeof config === 'object' ? { ...config } : {};
    if (!safe.coordinateOffset) {
        safe.coordinateOffset = { offsetX: 0, offsetY: 0 };
    } else {
        if (typeof safe.coordinateOffset.offsetX !== 'number') safe.coordinateOffset.offsetX = 0;
        if (typeof safe.coordinateOffset.offsetY !== 'number') safe.coordinateOffset.offsetY = 0;
    }
    if (!safe.displayConfig) {
        safe.displayConfig = { primaryWidth: 1920, primaryHeight: 1080, isMultiDisplay: false };
    } else {
        if (typeof safe.displayConfig.primaryWidth !== 'number') safe.displayConfig.primaryWidth = 1920;
        if (typeof safe.displayConfig.primaryHeight !== 'number') safe.displayConfig.primaryHeight = 1080;
        if (typeof safe.displayConfig.isMultiDisplay !== 'boolean') safe.displayConfig.isMultiDisplay = false;
    }
    if (!safe.fineTune) {
        safe.fineTune = { enableFineTune: true, stepSize: 20, maxOffset: 1000 };
    } else {
        if (typeof safe.fineTune.enableFineTune !== 'boolean') safe.fineTune.enableFineTune = true;
        if (typeof safe.fineTune.stepSize !== 'number') safe.fineTune.stepSize = 20;
        if (typeof safe.fineTune.maxOffset !== 'number') safe.fineTune.maxOffset = 1000;
    }
    // 新增：批量点击录制点
    if (!Array.isArray(safe.clickPoints)) {
        safe.clickPoints = [];
    }
    return safe;
}

// 加载配置
let CONFIG = ensureConfigDefaults(loadConfig());
if (!CONFIG) {
    CONFIG = ensureConfigDefaults({});
    saveConfig(CONFIG);
}

// ===== 用户配置区域 =====
// 如果点击位置不准确，请调整以下偏移值
const COORDINATE_OFFSET = CONFIG.coordinateOffset;

// 显示器配置
const DISPLAY_CONFIG = CONFIG.displayConfig;

// 坐标微调配置
const FINE_TUNE = CONFIG.fineTune;
// ========================

// 配置 nut-js - 设置鼠标移动速度
const { mouseSpeed } = require('@nut-tree-fork/nut-js');
if (mouseSpeed) {
    mouseSpeed(500);
}

// ===== 录制与批量点击 =====
const readline = require('readline');

function prompt(question) {
    return new Promise((resolve) => {
        const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
        rl.question(question, (answer) => {
            rl.close();
            resolve(answer);
        });
    });
}

async function recordPointsInteractive() {
    console.log('\n🎬 录制模式已开启');
    console.log('操作说明:');
    console.log('  - R: 记录当前鼠标位置');
    console.log('  - D: 删除最后一个点');
    console.log('  - C: 清空已记录的点');
    console.log('  - P: 打印当前点列表');
    console.log('  - S/Q: 保存并退出录制');

    const points = [];
    readline.emitKeypressEvents(process.stdin);
    if (process.stdin.isTTY && typeof process.stdin.setRawMode === 'function') {
        try { process.stdin.setRawMode(true); } catch (_) {}
    }
    // 确保 stdin 进入读取状态，避免在某些终端中直接退出
    if (typeof process.stdin.resume === 'function') {
        process.stdin.resume();
    }

    function printPoints() {
        if (points.length === 0) {
            console.log('（暂无记录）');
            return;
        }
        console.log('当前点列表:');
        points.forEach((p, idx) => {
            console.log(`  ${idx + 1}. (${p.x}, ${p.y})`);
        });
    }

    return new Promise((resolve) => {
        const onKey = async (str, key) => {
            const k = (key && key.name ? key.name : str).toLowerCase();
            if (k === 'r') {
                const pos = await mouse.getPosition();
                // 录制时反向扣除当前全局偏移，确保后续回放再加偏移能回到录制位置
                const rawX = pos.x - (COORDINATE_OFFSET.offsetX || 0);
                const rawY = pos.y - (COORDINATE_OFFSET.offsetY || 0);
                points.push({ x: rawX, y: rawY });
                console.log(`✅ 已记录: 实际(${pos.x}, ${pos.y}) -> 存储(${rawX}, ${rawY})，总计 ${points.length} 个`);
            } else if (k === 'd') {
                const removed = points.pop();
                if (removed) {
                    console.log(`🗑️ 已删除: (${removed.x}, ${removed.y})，剩余 ${points.length} 个`);
                } else {
                    console.log('⚠️ 无可删除的点');
                }
            } else if (k === 'c') {
                points.length = 0;
                console.log('🧹 已清空');
            } else if (k === 'p') {
                printPoints();
            } else if (k === 's' || k === 'q' || (key && key.sequence === '\r')) {
                // 保存
                const newConfig = ensureConfigDefaults(loadConfig() || CONFIG);
                newConfig.clickPoints = points;
                if (saveConfig(newConfig)) {
                    CONFIG = newConfig;
                    console.log('💾 点位已保存到配置文件');
                }
                process.stdin.off('keypress', onKey);
                if (process.stdin.isTTY && typeof process.stdin.setRawMode === 'function') {
                    try { process.stdin.setRawMode(false); } catch (_) {}
                }
                if (typeof process.stdin.pause === 'function') {
                    process.stdin.pause();
                }
                resolve(points);
            } else if (k === 'escape') {
                console.log('👋 已退出录制（未保存）');
                process.stdin.off('keypress', onKey);
                if (process.stdin.isTTY && typeof process.stdin.setRawMode === 'function') {
                    try { process.stdin.setRawMode(false); } catch (_) {}
                }
                if (typeof process.stdin.pause === 'function') {
                    process.stdin.pause();
                }
                resolve(points);
            }
        };
        process.stdin.on('keypress', onKey);
        console.log('▶ 等待按键（R/D/C/P/S/Q, Esc）...');
    });
}

async function executeClicks(options) {
    const {
        points,
        cycles = 1,
        perPointClicks = 1,
        delayBetweenClicksMs = 50,
        delayBetweenPointsMs = 200,
        delayBetweenCyclesMs = 500,
        applyOffset = false,
        enableCalibration = true
    } = options;

    if (!Array.isArray(points) || points.length === 0) {
        console.log('⚠️ 没有可点击的坐标');
        return;
    }

    // 预校准（可选）
    let deltaX = 0;
    let deltaY = 0;
    if (enableCalibration) {
        const first = points[0];
        let x0 = first.x + (applyOffset ? (COORDINATE_OFFSET.offsetX || 0) : 0);
        let y0 = first.y + (applyOffset ? (COORDINATE_OFFSET.offsetY || 0) : 0);
        await mouse.move(straightTo({ x: x0, y: y0 }));
        await new Promise(r => setTimeout(r, 100));

        console.log('\n🎯 快速校准模式（可选）');
        console.log('  W/A/S/D: 以1像素微调光标');
        console.log(`  按住Shift + W/A/S/D: 以${FINE_TUNE.stepSize}px微调`);
        console.log('  E: 重置偏移  Q或回车: 确认  Esc: 跳过');

        readline.emitKeypressEvents(process.stdin);
        if (process.stdin.isTTY && typeof process.stdin.setRawMode === 'function') {
            try { process.stdin.setRawMode(true); } catch (_) {}
        }
        if (typeof process.stdin.resume === 'function') process.stdin.resume();

        const done = await new Promise((resolve) => {
            const onKey = async (str, key) => {
                const name = (key && key.name ? key.name : str).toLowerCase();
                const step = (key && key.shift) ? (FINE_TUNE.stepSize || 20) : 1;
                if (name === 'w') { deltaY -= step; }
                else if (name === 's') { deltaY += step; }
                else if (name === 'a') { deltaX -= step; }
                else if (name === 'd') { deltaX += step; }
                else if (name === 'e') { deltaX = 0; deltaY = 0; }
                else if (name === 'q' || (key && key.sequence === '\r')) { resolve(true); return; }
                else if (name === 'escape') { deltaX = 0; deltaY = 0; resolve(true); return; }
                else { return; }
                await mouse.move(straightTo({ x: x0 + deltaX, y: y0 + deltaY }));
            };
            process.stdin.on('keypress', onKey);
            console.log('▶ 等待按键（W/A/S/D/E/Q, Enter, Esc）...');
            const cleanup = () => {
                process.stdin.off('keypress', onKey);
                if (process.stdin.isTTY && typeof process.stdin.setRawMode === 'function') {
                    try { process.stdin.setRawMode(false); } catch (_) {}
                }
                if (typeof process.stdin.pause === 'function') process.stdin.pause();
            };
            const finalize = (result) => { cleanup(); resolve(result); };
        });

        // 可选保存为全局偏移
        if (deltaX !== 0 || deltaY !== 0) {
            const ans = (await prompt(`是否将本次校准(ΔX=${deltaX}, ΔY=${deltaY}) 保存到全局偏移? y/N: `)).trim().toLowerCase();
            const yes = ans === 'y' || ans === 'yes' || ans === '是';
            if (yes) {
                const cfg = ensureConfigDefaults(loadConfig() || CONFIG);
                cfg.coordinateOffset.offsetX = (cfg.coordinateOffset.offsetX || 0) + deltaX;
                cfg.coordinateOffset.offsetY = (cfg.coordinateOffset.offsetY || 0) + deltaY;
                if (saveConfig(cfg)) {
                    CONFIG = cfg;
                    console.log('💾 已写入全局偏移');
                    // 既然已写入全局偏移，则后续不再叠加临时 delta
                    deltaX = 0; deltaY = 0;
                }
            }
        }
    }

    console.log(`\n🖱️ 开始执行: ${cycles} 轮, 每点点击 ${perPointClicks} 次`);
    for (let c = 1; c <= cycles; c++) {
        console.log(`\n— 第 ${c}/${cycles} 轮 —`);
        for (let i = 0; i < points.length; i++) {
            const base = points[i];
            let x = base.x + (applyOffset ? (COORDINATE_OFFSET.offsetX || 0) : 0) + deltaX;
            let y = base.y + (applyOffset ? (COORDINATE_OFFSET.offsetY || 0) : 0) + deltaY;
            console.log(`移动到第 ${i + 1} 个点: (${x}, ${y})`);
            await mouse.move(straightTo({ x, y }));
            await new Promise(r => setTimeout(r, 80));

            const isDouble = base && base.mode === 2;
            for (let k = 0; k < perPointClicks; k++) {
                if (isDouble) {
                    await mouse.doubleClick(Button.LEFT);
                } else {
                    await mouse.leftClick();
                }
                if (k < perPointClicks - 1) {
                    await new Promise(r => setTimeout(r, delayBetweenClicksMs));
                }
            }

            if (i < points.length - 1) {
                await new Promise(r => setTimeout(r, delayBetweenPointsMs));
            }
        }
        if (c < cycles) {
            await new Promise(r => setTimeout(r, delayBetweenCyclesMs));
        }
    }
    console.log('\n✅ 执行完成');
}

function showPoints(points) {
    if (!Array.isArray(points) || points.length === 0) {
        console.log('（暂无已保存的坐标）');
        return;
    }
    console.log('已保存坐标:');
    points.forEach((p, i) => console.log(`  ${i + 1}. (${p.x}, ${p.y})`));
}

async function main() {
    console.log('🚀 启动录制/批量点击程序');
    console.log('📋 当前偏移: ' +
        `X${COORDINATE_OFFSET.offsetX >= 0 ? '+' : ''}${COORDINATE_OFFSET.offsetX}, ` +
        `Y${COORDINATE_OFFSET.offsetY >= 0 ? '+' : ''}${COORDINATE_OFFSET.offsetY}`);

    while (true) {
        console.log('\n===== 主菜单 =====');
        console.log('1) 录制坐标');
        console.log('2) 执行点击');
        console.log('3) 查看已保存坐标');
        console.log('4) 清空已保存坐标');
        console.log('5) 退出');

        const choice = (await prompt('请选择 [1-5]: ')).trim();
        if (choice === '1') {
            await recordPointsInteractive();
        } else if (choice === '2') {
            const cfg = ensureConfigDefaults(loadConfig() || CONFIG);
            const points = cfg.clickPoints || [];
            if (!points.length) {
                console.log('⚠️ 未找到坐标，请先录制');
                continue;
            }
            const cycles = parseInt((await prompt('执行轮数 (默认1): ')).trim() || '1', 10);
            const perPointClicks = parseInt((await prompt('每个点点击次数 (默认1): ')).trim() || '1', 10);
            const delayBetweenClicksMs = parseInt((await prompt('单点内点击间隔ms (默认50): ')).trim() || '50', 10);
            const delayBetweenPointsMs = parseInt((await prompt('点与点之间间隔ms (默认200): ')).trim() || '200', 10);
            const delayBetweenCyclesMs = parseInt((await prompt('轮与轮之间间隔ms (默认500): ')).trim() || '500', 10);
            const applyOffsetAns = (await prompt('是否应用全局偏移? y/N: ')).trim().toLowerCase();
            const applyOffset = applyOffsetAns === 'y' || applyOffsetAns === 'yes' || applyOffsetAns === '是';
            const enableCalibrationAns = (await prompt('执行前是否进入快速校准? Y/n: ')).trim().toLowerCase();
            const enableCalibration = enableCalibrationAns === '' || enableCalibrationAns === 'y' || enableCalibrationAns === 'yes' || enableCalibrationAns === '是';

            await executeClicks({
                points,
                cycles: Number.isFinite(cycles) ? cycles : 1,
                perPointClicks: Number.isFinite(perPointClicks) ? perPointClicks : 1,
                delayBetweenClicksMs: Number.isFinite(delayBetweenClicksMs) ? delayBetweenClicksMs : 50,
                delayBetweenPointsMs: Number.isFinite(delayBetweenPointsMs) ? delayBetweenPointsMs : 200,
                delayBetweenCyclesMs: Number.isFinite(delayBetweenCyclesMs) ? delayBetweenCyclesMs : 500,
                applyOffset,
                enableCalibration,
            });
        } else if (choice === '3') {
            const cfg = ensureConfigDefaults(loadConfig() || CONFIG);
            showPoints(cfg.clickPoints);
        } else if (choice === '4') {
            const cfg = ensureConfigDefaults(loadConfig() || CONFIG);
            cfg.clickPoints = [];
            if (saveConfig(cfg)) {
                CONFIG = cfg;
                console.log('🧹 已清空并保存');
            }
        } else if (choice === '5') {
            console.log('👋 退出');
            break;
        } else {
            console.log('❓ 无效选择');
        }
    }
}

// 运行主程序
main();